/**
 * Copyleft (C) 2023-2024 maminjie <canpool@163.com>
 * SPDX-License-Identifier: BSD-3-Clause
 **/
#ifndef QXMATERIALSLIDER_P_H
#define QXMATERIALSLIDER_P_H

#include "qxmaterial_global.h"
#include <QColor>
#include <QRectF>
#include <QStateMachine>
#include "matoverlaywidget.h"

QX_MATERIAL_BEGIN_NAMESPACE

class MatSlider;
class MatSliderThumb;
class MatSliderTrack;
class MatSliderStateMachine;

class MatSliderPrivate
{
    Q_DISABLE_COPY(MatSliderPrivate)
    Q_DECLARE_PUBLIC(MatSlider)
public:
    MatSliderPrivate(MatSlider *q);
    ~MatSliderPrivate();

    void init();

    QRectF trackBoundingRect() const;
    QRectF thumbBoundingRect() const;

    int valueFromPosition(const QPoint &pos) const;

    void setHovered(bool status);

    MatSlider *const q_ptr;
    MatSliderThumb *thumb;
    MatSliderTrack *track;
    MatSliderStateMachine *stateMachine;
    QColor thumbColor;
    QColor trackColor;
    QColor disabledColor;
    int stepTo;
    int oldValue;
    int trackWidth;
    bool hoverTrack;
    bool hoverThumb;
    bool hover;
    bool step;
    bool pageStepMode;
    bool useThemeColors;
};

class MatSliderStateMachine : public QStateMachine
{
    Q_OBJECT
public:
    MatSliderStateMachine(MatSlider *slider, MatSliderThumb *thumb, MatSliderTrack *track);
    ~MatSliderStateMachine();

    void setupProperties();
private:
    Q_DISABLE_COPY(MatSliderStateMachine)

    MatSlider *const m_slider;
    MatSliderThumb *const m_thumb;
    MatSliderTrack *const m_track;
    QState *const m_topState;
    QState *const m_fstState;
    QState *const m_sndState;
    QState *const m_inactiveState;
    QState *const m_focusState;
    QState *const m_slidingState;
    QState *const m_pulseOutState;
    QState *const m_pulseInState;
    QState *const m_minState;
    QState *const m_normalState;
};

class MatSliderThumb : public MatOverlayWidget
{
    Q_OBJECT

    Q_PROPERTY(qreal diameter WRITE setDiameter READ diameter)
    Q_PROPERTY(qreal borderWidth WRITE setBorderWidth READ borderWidth)
    Q_PROPERTY(QColor borderColor WRITE setBorderColor READ borderColor)
    Q_PROPERTY(QColor fillColor WRITE setFillColor READ fillColor)
    Q_PROPERTY(qreal haloSize WRITE setHaloSize READ haloSize)
    Q_PROPERTY(QColor haloColor WRITE setHaloColor READ haloColor)
public:
    explicit MatSliderThumb(MatSlider *slider);
    ~MatSliderThumb();

    inline void setDiameter(qreal diameter);
    inline qreal diameter() const;

    inline void setBorderWidth(qreal width);
    inline qreal borderWidth() const;

    inline void setBorderColor(const QColor &color);
    inline QColor borderColor() const;

    inline void setFillColor(const QColor &color);
    inline QColor fillColor() const;

    inline void setHaloSize(qreal size);
    inline qreal haloSize() const;

    inline void setHaloColor(const QColor &color);
    inline QColor haloColor() const;

    inline void setOffset(int offset);
    inline int offset() const;
protected:
    bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE;
    void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
private:
    Q_DISABLE_COPY(MatSliderThumb)

    const MatSlider *const m_slider;
    QColor m_borderColor;
    QColor m_fillColor;
    QColor m_haloColor;
    qreal m_diameter;
    qreal m_borderWidth;
    qreal m_haloSize;
    int m_offset;
};

inline void MatSliderThumb::setDiameter(qreal diameter)
{
    m_diameter = diameter;
    update();
}

inline qreal MatSliderThumb::diameter() const
{
    return m_diameter;
}

inline void MatSliderThumb::setBorderWidth(qreal width)
{
    m_borderWidth = width;
    update();
}

inline qreal MatSliderThumb::borderWidth() const
{
    return m_borderWidth;
}

inline void MatSliderThumb::setBorderColor(const QColor &color)
{
    m_borderColor = color;
    update();
}

inline QColor MatSliderThumb::borderColor() const
{
    return m_borderColor;
}

inline void MatSliderThumb::setFillColor(const QColor &color)
{
    m_fillColor = color;
    update();
}

inline QColor MatSliderThumb::fillColor() const
{
    return m_fillColor;
}

inline void MatSliderThumb::setHaloSize(qreal size)
{
    m_haloSize = size;
    update();
}

inline qreal MatSliderThumb::haloSize() const
{
    return m_haloSize;
}

inline void MatSliderThumb::setHaloColor(const QColor &color)
{
    m_haloColor = color;
    update();
}

inline QColor MatSliderThumb::haloColor() const
{
    return m_haloColor;
}

inline void MatSliderThumb::setOffset(int offset)
{
    m_offset = offset;
    update();
}

inline int MatSliderThumb::offset() const
{
    return m_offset;
}

class MatSliderTrack : public MatOverlayWidget
{
    Q_OBJECT

    Q_PROPERTY(QColor fillColor WRITE setFillColor READ fillColor)
public:
    explicit MatSliderTrack(MatSliderThumb *thumb, MatSlider *slider);
    ~MatSliderTrack();

    inline void setFillColor(const QColor &color);
    inline QColor fillColor() const;

    inline void setTrackWidth(int width);
    inline int trackWidth() const;
protected:
    bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE;
    void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
private:
    Q_DISABLE_COPY(MatSliderTrack)

    const MatSlider *const m_slider;
    MatSliderThumb *const m_thumb;
    QColor m_fillColor;
    int m_trackWidth;
};

inline void MatSliderTrack::setFillColor(const QColor &color)
{
    m_fillColor = color;
    update();
}

inline QColor MatSliderTrack::fillColor() const
{
    return m_fillColor;
}

void MatSliderTrack::setTrackWidth(int width)
{
    m_trackWidth = width;
    update();
}

int MatSliderTrack::trackWidth() const
{
    return m_trackWidth;
}

QX_MATERIAL_END_NAMESPACE

#endif   // QXMATERIALSLIDER_P_H
